Allows Vulkan spec constants as attribute arguments.#7439
Allows Vulkan spec constants as attribute arguments.#7439danbrown-amd wants to merge 1 commit intomicrosoft:mainfrom
Conversation
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
9db3b6c to
243acbc
Compare
s-perron
left a comment
There was a problem hiding this comment.
I don't mind this change generally. It will be good for SPIR-V.
I don't know if this is complete yet (it is still a draft). I pointed out one issue with using LocalSize. You might also need to look at SpirvEmitter::addDerivativeGroupExecutionMode(). That function determines which derivative group execution mode to add based on the number of threas in the group. However, if you have a spec constant for the number of threads, we cannot do that.
357813d to
8e898bf
Compare
|
Why was Of course, since there's no access to specializations at compile time, there's no way to ensure the best choice of execution mode with spec constants anyway. However, in some cases partial information would be sufficient to rule out one of them. If both are possible, maybe pick one and issue a warning? |
It was implemented that way because that was the HLSL spec implemented for DXIL. See Thread Groups and Quads. I don't mind if we diverge from it when there are specialization constants. We just need to document it.
That is a reasonable idea. Longer term, we could try to add explicit attribute that apply to the entry point that would override the guess. |
s-perron
left a comment
There was a problem hiding this comment.
LGTM, but requires some tests.
llvm-beanz
left a comment
There was a problem hiding this comment.
I think there is a lot of missing test coverage here. You're making a bunch of attributes that had previously either required integer literal arguments or optional integer literal arguments now support constant expressions and specialization constants.
We really need test coverage for each attribute's change in behavior, and the error states. In particular it doesn't seem to me like you're actually handling the possible error of a non-constant expression being provided as a value. I think it just silently replaces the value with the default (which would be bad).
| } // namespace | ||
|
|
||
| static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, | ||
| uint32_t defaultVal = 0) { |
There was a problem hiding this comment.
| uint32_t defaultVal = 0) { | |
| uint32_t defaultVal) { |
Doesn't look like this is ever called without a default value.
There was a problem hiding this comment.
I've changed this to use llvm::Optional so that an absent default indicates that expr should be non-null. (See note on SemaHLSL below.)
| const uint NumThreadsY = 1; | ||
| #endif | ||
|
|
||
| [numthreads(NumThreadsX,NumThreadsY,1)] |
There was a problem hiding this comment.
Some other test cases that are probably interesting:
uint CBufferValue;
[numthreads(CbufferValue, 1, 1)] // Should error
void main() {} const uint Eight = 8;
[numthreads(Eight * 2, Eight, 1)] // Should work
void main() {} There was a problem hiding this comment.
The latter won't work but would if declared static. Larger expressions incorporating spec constants don't work in the current version.
I've added preprocessor directives to vk.spec-constants.attributes.hlsl to enable removal of the spec constant designations to test for expected errors.
| static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, | ||
| uint32_t defaultVal = 0) { |
There was a problem hiding this comment.
| static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, | |
| uint32_t defaultVal = 0) { | |
| static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, | |
| uint32_t defaultVal) { |
It is really unfortunate to completely duplicate this code, and I don't think the two should be identical. In this version in Sema we should be surfacing an error if there is an expression that isn't a constant expression or spec constant.
There was a problem hiding this comment.
Sema already seems to complain in all the relevant cases, though I have added some more diagnostics. Of the arguments allowed to be spec constants, the only optional one is the NodeId index, so maybe just return zero (possibly after issuing an error) whenever expr is null? For now the function works as described for the CGHLSLMS version.
| return (uint32_t)apsInt.getSExtValue(); | ||
| if (expr->isVulkanSpecConstantExpr(astContext, &apValue) && apValue.isInt()) | ||
| return (uint32_t)apValue.getInt().getSExtValue(); | ||
| } |
There was a problem hiding this comment.
| } | |
| llvm_unreachable("Expression must be a constant expression or spec constant") | |
| } |
We should be erroring in Sema if this isn't a constant expression or spec constant.
There was a problem hiding this comment.
Changed as suggested.
| }; | ||
| } // namespace | ||
|
|
||
| static uint32_t GetIntConstAttrArg(ASTContext &astContext, const Expr *expr, |
There was a problem hiding this comment.
You've got a fair amount of mixing coding style, and DXC is a bit inconsistent.
In general if you're adding code in a part of the codebase that isn't otherwise following a consistent style we follow the LLVM Coding Standards. LLVM uses CamelCase for variable names and type names (see: https://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly).
|
/AzurePipelines run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
58b3508 to
21fdad3
Compare
Fixes #3092